package com.frank.loadinglibrary.special;

import com.frank.loadinglibrary.ResourceTable;
import com.frank.loadinglibrary.common.BallBeatLoadComponent;
import com.frank.loadinglibrary.utils.Indicator;
import ohos.agp.animation.AnimatorGroup;
import ohos.agp.animation.AnimatorValue;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.render.*;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.agp.utils.Matrix;
import ohos.agp.utils.RectFloat;
import ohos.agp.utils.TextAlignment;
import ohos.app.Context;
import ohos.global.resource.NotExistException;
import ohos.global.resource.Resource;
import ohos.global.resource.WrongTypeException;
import ohos.hiviewdfx.HiLog;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.media.image.common.PixelFormat;
import ohos.media.image.common.Size;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;

public class TitanicLoadComponent extends Component implements Component.DrawTask {


    private boolean isAllow = true;

    private PixelMap wave;
    private PixelMapShader shader;

    private Paint textPaint;
    private Color textColor = new Color(Color.getIntColor("#212121"));
    // shader matrix
    private Matrix shaderMatrix;
    private float maskX, maskY;
    private float offsetY;

    private Indicator<AnimatorGroup> indicator;

    private int reverse = 1;
    float height;
    private PixelMapHolder mShapePixMapHold;
    private int mWaveLenth = 150;
    private float offset;
    private Font textFont;
    private String drawText;

    public TitanicLoadComponent(Context context) {
        this(context, null);
    }

    public TitanicLoadComponent(Context context, AttrSet attarSet) {
        this(context, attarSet, "");
    }

    public TitanicLoadComponent(Context context, AttrSet attrSet, String styleName) {
        super(context, attrSet, styleName);
        initFont();
        HiLog.debug(BallBeatLoadComponent.label, "TitanicLoadComponent start ");
        init();
        setBindStateChangedListener(new BindStateChangedListener() {
            @Override
            public void onComponentBoundToWindow(Component component) {
                indicator.start();
            }

            @Override
            public void onComponentUnboundFromWindow(Component component) {

            }
        });
        addDrawTask(this);
    }

    private void init() {


        textPaint = new Paint();
        String path = getContext().getCacheDir() + "/test.ttf";
        File file = new File(path);
        textFont = new Font.Builder(file).build();

        try {
            drawText = getResourceManager().getElement(ResourceTable.String_loading).getString();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (NotExistException e) {
            e.printStackTrace();
        } catch (WrongTypeException e) {
            e.printStackTrace();
        } finally {
            if (drawText == null || "".equals(drawText)) {
                drawText = "Loading";
            }
        }
        shaderMatrix = new Matrix();
        textPaint.setStyle(Paint.Style.FILL_STYLE);
        textPaint.setStrokeWidth(8);
        textPaint.setTextSize(100);
        textPaint.setTextAlign(TextAlignment.CENTER);
        textPaint.setColor(textColor);
//        textPaint.setFont(new Font.Builder("").build());
        indicator = new Indicator<AnimatorGroup>() {
            @Override
            public ArrayList<AnimatorGroup> onCreateAnimators() {
                AnimatorValue maskXAnimator = new AnimatorValue();
                maskXAnimator.setDuration(1000);
                maskXAnimator.setLoopedCount(AnimatorValue.INFINITE);
                maskXAnimator.setValueUpdateListener((animatorValue, v) -> {
                    maskX = 200 * v;
                    offset = mWaveLenth * v;
                    invalidate();
                });

                AnimatorValue maskYAnimator = new AnimatorValue();
                maskYAnimator.setDuration(10000);
                maskYAnimator.setLoopedCount(AnimatorValue.INFINITE);
                maskYAnimator.setValueUpdateListener((animatorValue, v) -> {
                    if (v <= 0.5f) {
                        maskY = (70f) * (0.5f - v) / 0.5f * reverse;
                    } else {
                        maskY = (70f) * (0.5f - v) / 0.5f * reverse;
                    }
//                    HiLog.debug(BallBeatLoadComponent.label,"onDraw maskYAnimator "+maskY + "-"+v +"-"+height);
//                    System.out.println("onDraw maskYAnimator "+maskY + "-"+v +"-"+height);
                    invalidate();
                });
                maskYAnimator.setLoopedListener(animator -> {
                    reverse *= -1;
                });

                AnimatorGroup animatorGroup = new AnimatorGroup();
                animatorGroup.setLoopedCount(-1);
                AnimatorGroup.Builder animatorGroupBuilder = animatorGroup.build();
                animatorGroupBuilder.addAnimators(maskXAnimator, maskYAnimator);

                ArrayList<AnimatorGroup> list = new ArrayList<>();
                list.add(animatorGroup);
                return list;
            }
        };
    }

    protected void stopAnimators() {

    }

    protected void startAnimators() {

    }

    @Override
    public void onDraw(Component component, Canvas canvas) {
        height = getHeight();
        RectFloat rectF = new RectFloat(0, 0, getWidth(), getHeight());
        //计算baseline
        Paint.FontMetrics fontMetrics = textPaint.getFontMetrics();
        float distance = (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.bottom;
        float baseline = rectF.getCenter().getPointY() + distance;
        if (mShapePixMapHold == null) {
            try {
                createShader2();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (NotExistException e) {
                e.printStackTrace();
            }
        }

        int mLayerId = canvas.saveLayer(new RectFloat(0, 0, getWidth(), getHeight()), textPaint);
        textPaint.setFont(textFont);
        canvas.drawText(textPaint, drawText, rectF.getCenter().getPointX(), baseline);
        textPaint.setBlendMode(BlendMode.SRC_IN);
        canvas.drawPixelMapHolder(mShapePixMapHold, maskX, maskY, textPaint);
        textPaint.setBlendMode(null);
        canvas.restoreToCount(mLayerId);
//        getWavePath(canvas);

    }


    public void draw2(Canvas canvas, String text, RectFloat rectF, float baseline) {
        RectFloat mRectF = new RectFloat(0, 0, getWidth(), getHeight());
        int mLayerId = canvas.saveLayer(new RectFloat(0, 0, getWidth(), getHeight()), textPaint);
        canvas.drawText(textPaint, text, rectF.getCenter().getPointX(), baseline);
        textPaint.setBlendMode(BlendMode.SRC_IN);
        canvas.drawPixelMapHolder(mShapePixMapHold, maskX, maskY, textPaint);
        textPaint.setBlendMode(null);
        canvas.restoreToCount(mLayerId);
    }

    private void createShader() throws IOException, NotExistException {
        Resource media = getContext().getResourceManager().getResource(ResourceTable.Media_wave);
        ImageSource.SourceOptions Soptions = new ImageSource.SourceOptions();
        ImageSource imageSource = ImageSource.create(media, Soptions);
        ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
        wave = imageSource.createPixelmap(decodingOptions);


        int waveW = wave.getImageInfo().size.width;
        int waveH = wave.getImageInfo().size.height;
        PixelMap.InitializationOptions options = new PixelMap.InitializationOptions();
        options.pixelFormat = PixelFormat.ARGB_8888;
        options.size = new Size(getWidth(), waveH);
        options.editable = true;
        PixelMap defaultPixmap = PixelMap.create(options);


        //根据图片生成Texture(由像素组成的像素映射文件)
        Texture tt = new Texture(defaultPixmap);
        //将指定图像绘制到canva
        PixelMapHolder pixelMapHolder = new PixelMapHolder(wave);
        //设置颜色的亮度
        ColorMatrix lumMatrix = new ColorMatrix();
        lumMatrix.setSaturation(3);
        Paint paint = new Paint();
        Canvas canvas = new Canvas(tt);
        canvas.drawColor(textColor.getValue(), BlendMode.SRC);
        canvas.drawPixelMapHolder(pixelMapHolder, 0, 0, paint);
        mShapePixMapHold = new PixelMapHolder(defaultPixmap);
        shader = new PixelMapShader(mShapePixMapHold, Shader.TileMode.REPEAT_TILEMODE, Shader.TileMode.CLAMP_TILEMODE);
//        textPaint.setShader(shader,Paint.ShaderType.PIXELMAP_SHADER);
    }


    private void createShader2() throws IOException, NotExistException {
        Resource media = getContext().getResourceManager().getResource(ResourceTable.Media_wave);
        ImageSource.SourceOptions Soptions = new ImageSource.SourceOptions();
        ImageSource imageSource = ImageSource.create(media, Soptions);
        ImageSource.DecodingOptions decodingOptions = new ImageSource.DecodingOptions();
        wave = imageSource.createPixelmap(decodingOptions);


        int waveW = wave.getImageInfo().size.width;
        int waveH = wave.getImageInfo().size.height;
        PixelMap.InitializationOptions options = new PixelMap.InitializationOptions();
        options.pixelFormat = PixelFormat.ARGB_8888;
        options.size = new Size(getWidth(), waveH);
        options.editable = true;
        PixelMap defaultPixmap = PixelMap.create(options);

        //根据图片生成Texture(由像素组成的像素映射文件)
        Texture tt = new Texture(defaultPixmap);
        //将指定图像绘制到canva
        PixelMapHolder pixelMapHolder = new PixelMapHolder(wave);
        //设置颜色的亮度
        ColorMatrix lumMatrix = new ColorMatrix();
        lumMatrix.setSaturation(3);
        Paint paint = new Paint();
        Canvas canvas = new Canvas(tt);
        canvas.drawColor(textColor.getValue(), BlendMode.SRC);
        int count = (getWidth() + waveW - 1) / waveW;

        for (int idx = 0; idx < count; ++idx) {
            canvas.drawPixelMapHolder(pixelMapHolder, idx * waveW, 0, paint);
        }
        mShapePixMapHold = new PixelMapHolder(defaultPixmap);

    }

    private void getWavePath(Canvas canvas) {
        int mWaveCount = (int) Math.round(getWidth() / mWaveLenth + 1.5); // 计算波形的个数
        Path mPath = new Path();
        mPath.reset();
        float mCenterY = getHeight() / 2f;
        mPath.moveTo(-mWaveLenth, mCenterY);
        for (int i = 0; i < mWaveCount; i++) {
            mPath.quadTo(-mWaveLenth * 3 / 4 + i * mWaveLenth + offset, mCenterY + 60, -mWaveLenth / 2 + i * mWaveLenth + offset, mCenterY);
            mPath.quadTo(-mWaveLenth / 4 + i * mWaveLenth + offset, mCenterY - 60, i * mWaveLenth + offset, mCenterY);
        }
        mPath.lineTo(getWidth(), getHeight());
        mPath.lineTo(0, getHeight());
        mPath.close();
        canvas.drawPath(mPath, textPaint);

    }

    private void initFont() {
        Resource FI = null;
        FileOutputStream fos = null;
        try {
            FI = getResourceManager().getRawFileEntry("resources/rawfile/Satisfy-Regular.ttf").openRawFile();
            String path = getContext().getCacheDir() + "/test.ttf";
            HiLog.debug(BallBeatLoadComponent.label, "initFont path " + path);
            fos = new FileOutputStream(path);

            byte[] buffer = new byte[4096];
            int count = 0;
            while ((count = FI.read(buffer)) != -1) {
                fos.write(buffer, 0, count);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fos != null) {
                try {
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (FI != null) {
                try {
                    FI.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }
}
